package com.lintf.bot.wechat.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lintf.bot.wechat.IWeChatNoticeService;
import com.lintf.bot.wechat.dto.NotificationsSendDTO;
import com.lintf.common.core.domain.entity.SysUser;
import com.lintf.common.utils.DateUtils;
import com.lintf.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ system:Mac
 * @ author:lin tingfeng
 * @ data:2024/1/16 15:01
 * @ package_name:com.lintf.system.service.weChat.impl
 * @ project_name:mobile-project
 * @ desc:
 */
@Slf4j
@Service
public class WeChatNoticeServiceImpl implements IWeChatNoticeService {

    @Value("${wx.notificationUrl}")
    private String notificationUrl;
    @Value("${wx.sendLikeNotificationsTemplateId}")
    private String sendLikeNotificationsTemplateId;
    @Value("${wx.sendNotificationsTemplateId}")
    private String sendNotificationsTemplateId;
    @Value("${wx.miniprogramState}")
    private String miniprogramState;
    @Value("${wx.lang}")
    private String lang;
    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.appSecret}")
    private String appSecret;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ISysUserService sysUserService;

    private String accessToken;
    private long accessTokenTimestamp = 0;
    private long accessTokenExpiresIn = 0;

    @Override
    public void sendNotifications(NotificationsSendDTO dto) {
        log.info("======开始进行消息推送======");
        StringBuilder requestUrl = new StringBuilder()
                .append(notificationUrl)
                .append(dto.getAccessToken());
//        List<SysUser> sysUsers = sysUserService.selectUserListBySendNotifications();
//        BotGroupInviteListDTO listDTO = new BotGroupInviteListDTO();
//        listDTO.setGroupId(dto.getGroupId());
//        listDTO.setIncludeOfOwn(false);
//        List<SysUser> sysUsers = botGroupInviteService.getGroupOfUser(listDTO);
        List<SysUser> sysUsers = dto.getSysUsers();
        log.info("======开始进行消息推送,预计推送用户数量：{}个======", sysUsers.size());
        sysUsers.stream().filter(item -> !Objects.equals(item.getUserId(), dto.getCurrentUserId()) && StringUtils.isNotEmpty(item.getOpenId())).forEach(item -> {
            log.info("======开始进行消息推送,推送用户：{}======", item.getNickName());
            JSONObject object = new JSONObject();
            object.put("touser", item.getOpenId());
            object.put("template_id", sendNotificationsTemplateId);
            object.put("page", "/pages/enter");
            JSONObject data = new JSONObject();
            JSONObject title = new JSONObject();
            title.put("value", dto.getTitle());
            JSONObject content = new JSONObject();
            content.put("value", dto.getContent());
            JSONObject publishTime = new JSONObject();
            String formatted = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, dto.getPublishTime());
            publishTime.put("value", formatted);
            JSONObject nickName = new JSONObject();
            nickName.put("value", dto.getNickName());
            data.put("short_thing19", title);
            data.put("thing5", content);
            data.put("time18", publishTime);
            data.put("thing17", nickName);
            object.put("data", data);
            object.put("miniprogram_state", miniprogramState);
            object.put("lang", lang);
            ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(requestUrl.toString(), object, String.class);
            String responseData = stringResponseEntity.getBody();
            JSONObject parseObject = JSONObject.parseObject(responseData);
            String errMsg = parseObject.get("errmsg").toString();
            log.info("======开始进行消息推送,推送用户：{}，状态：{}======", item.getNickName(), errMsg);
        });
        log.info("======消息推送推送完毕======");
    }

    @Override
    public void sendLikeNotifications(NotificationsSendDTO dto) {
        if (Objects.equals(dto.getPublishUserId(), dto.getCurrentUserId())) {
            return;
        }
        log.info("======开始进行消息推送======");
        StringBuilder requestUrl = new StringBuilder()
                .append(notificationUrl)
                .append(dto.getAccessToken());
        SysUser sysUsers = sysUserService.selectUserById(dto.getPublishUserId());
        sendWxNotification(dto, requestUrl, sysUsers);
        log.info("======消息推送推送完毕======");
    }

    @Override
    public void sendItemNotifications(NotificationsSendDTO dto) {
        if (dto.getSysUsers().isEmpty()) {
            return;
        }
        List<SysUser> collected = dto.getSysUsers().stream().filter(item -> !Objects.equals(item.getUserId(), dto.getCurrentUserId())).collect(Collectors.toList());
        if (collected.isEmpty()) {
            return;
        }
        log.info("======开始进行消息推送======");
        StringBuilder requestUrl = new StringBuilder()
                .append(notificationUrl)
                .append(dto.getAccessToken());
        log.info("======开始进行消息推送,预计推送用户数量：{}个======", dto.getSysUsers().size());
        for (SysUser sysUser : collected) {
            sendWxNotification(dto, requestUrl, sysUser);
        }
        log.info("======消息推送推送完毕======");
    }

    private void sendWxNotification(NotificationsSendDTO dto, StringBuilder requestUrl, SysUser sysUser) {
        String publishNickName = sysUser.getNickName();
        log.info("======开始进行消息推送,推送用户：{}======", publishNickName);
        JSONObject object = new JSONObject();
        object.put("touser", sysUser.getOpenId());
        object.put("template_id", sendLikeNotificationsTemplateId);
        object.put("page", "/pages/enter");
        JSONObject data = new JSONObject();
        JSONObject title = new JSONObject();
        title.put("value", dto.getTitle());
        JSONObject nickName = new JSONObject();
        nickName.put("value", dto.getCurrentNickName());
        data.put("thing1", title);
        data.put("thing3", nickName);
        object.put("data", data);
        object.put("miniprogram_state", miniprogramState);
        object.put("lang", lang);
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(requestUrl.toString(), object, String.class);
        String responseData = stringResponseEntity.getBody();
        JSONObject parseObject = JSONObject.parseObject(responseData);
        String errMsg = parseObject.get("errmsg").toString();
        log.info("======开始进行消息推送,推送用户：{}，状态：{}======", publishNickName, errMsg);
    }

    /**
     * 获取accesstoken
     *
     * @return
     */
    @Override
    public String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + appSecret;
        if (isAccessTokenExpired()) {
            log.info("======检测到accessToken已过期======");
            log.info("======正在请求新的accessToken======");
            try {
                String resultString = restTemplate.getForObject(url, String.class);
                log.info("获取微信accessToken:{}", resultString);
                if (StringUtils.isNotEmpty(resultString)) {
                    JSONObject jsonObject = JSON.parseObject(resultString);
                    accessToken = jsonObject.get("access_token").toString();
                    updateAccessTokenExpirationTime(Long.parseLong(jsonObject.get("expires_in").toString()));
                } else {
                    log.error("返回值为空，请检查请求报文或者请求地址是否正确");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        log.info("======成功获取到accessToken======");
        return accessToken;
    }

    private boolean isAccessTokenExpired() {
        // 根据实际需求，判断 accessToken 是否已过期
        // 可以通过记录 accessToken 的获取时间和有效期，与当前时间进行对比来判断是否过期
        long currentTime = System.currentTimeMillis() / 1000;  // 获取当前时间戳（单位：秒）
        return (accessTokenTimestamp + accessTokenExpiresIn) < currentTime;
    }

    private void updateAccessTokenExpirationTime(long expiresIn) {
        // 更新 accessToken 的过期时间
        accessTokenTimestamp = System.currentTimeMillis() / 1000;  // 记录更新时间戳（单位：秒）
        accessTokenExpiresIn = expiresIn;
    }
}
